//********************************************************************************************************************************
//*                                                                                                                              *
//*     Image Recognition Library 1.0.40.49  3delite 2011-2021                                                                  *
//*     See Image Recognition Library ReadMe.txt for details                                                                     *
//*                                                                                                                              *
//* Licenses available for usage of this library:                                                                                *
//* Freeware License: 25                                                                                                        *
//*     http://www.shareit.com/product.html?productid=300983850                                                                  *
//* Shareware License: 50                                                                                                       *
//*     http://www.shareit.com/product.html?productid=300486940                                                                  *
//* Commercial License: 250                                                                                                     *
//*     http://www.shareit.com/product.html?productid=300486939                                                                  *
//*                                                                                                                              *
//*     https://www.3delite.hu/Object%20Pascal%20Developer%20Resources/ImageRecognitionLibrary.html                              *
//*                                                                                                                              *
//* If you have any questions or enquiries please mail: 3delite@3delite.hu                                                       *
//*                                                                                                                              *
//* Good coding! :)                                                                                                              *
//* 3delite                                                                                                                      *
//********************************************************************************************************************************

unit ImageRecognitionDefs;

interface

{$IFDEF MSWINDOWS}
Uses
    Windows;
{$ENDIF}

type
    Bool = LongBool;

const
    NAME_ImageRecognition_CreateObject                  = 'ImageRecognition_CreateObject';
    NAME_ImageRecognition_FreeObject                    = 'ImageRecognition_FreeObject';
    NAME_ImageRecognition_Compare                       = 'ImageRecognition_Compare';
    NAME_ImageRecognition_FreeResult                    = 'ImageRecognition_FreeResult';
    NAME_ImageRecognition_CreateObjectFromBitmapHandle  = 'ImageRecognition_CreateObjectFromBitmapHandle';
    NAME_ImageRecognition_CreateObjectFromMemory        = 'ImageRecognition_CreateObjectFromMemory';
    NAME_ImageRecognition_OpenCLGetPlatform             = 'ImageRecognition_OpenCLGetPlatform';
    NAME_ImageRecognition_OpenCLGetPlatformDevice       = 'ImageRecognition_OpenCLGetPlatformDevice';
    NAME_ImageRecognition_OpenCLInit                    = 'ImageRecognition_OpenCLInit';
    NAME_ImageRecognition_OpenCLFree                    = 'ImageRecognition_OpenCLFree';
    NAME_ImageRecognition_OpenCLSetSearchIn             = 'ImageRecognition_OpenCLSetSearchIn';
    NAME_ImageRecognition_OpenCLSetSearchFor            = 'ImageRecognition_OpenCLSetSearchFor';
    NAME_ImageRecognition_OpenCLPerformSearch           = 'ImageRecognition_OpenCLPerformSearch';
    NAME_ImageRecognition_CreateSearchQueue             = 'ImageRecognition_CreateSearchQueue';
    NAME_ImageRecognition_FreeSearchQueue               = 'ImageRecognition_FreeSearchQueue';
    NAME_ImageRecognition_AddSearchWork                 = 'ImageRecognition_AddSearchWork';
    NAME_ImageRecognition_FreeSearchQueueResult         = 'ImageRecognition_FreeSearchQueueResult';
    NAME_ImageRecognition_AbortSearchQueue              = 'ImageRecognition_AbortSearchQueue';
    NAME_ImageRecognition_CreateLoadQueue               = 'ImageRecognition_CreateLoadQueue';
    NAME_ImageRecognition_FreeLoadQueue                 = 'ImageRecognition_FreeLoadQueue';
    NAME_ImageRecognition_AddLoadWork                   = 'ImageRecognition_AddLoadWork';
    NAME_ImageRecognition_AddLoadWorkBitmapHandle       = 'ImageRecognition_AddLoadWorkBitmapHandle';
    NAME_ImageRecognition_FreeLoadQueueResult           = 'ImageRecognition_FreeLoadQueueResult';
    NAME_ImageRecognition_AbortLoadQueue                = 'ImageRecognition_AbortLoadQueue';

const
    {$IFDEF MSWINDOWS}
    ImageRecognitionLibraryName = 'ImageRecognition.dll';
    {$ENDIF}
    {$IFDEF MACOS}
    ImageRecognitionLibraryName = 'libImageRecognition.dylib';
    {$ENDIF}

//* Error codes
const
    IR_OK                           = 0;
    IR_ERROR_UNKNOWN                = 1;
    IR_ERROR_NOT_ENOUGH_MEMORY      = 2;
    IR_ERROR_LOADING                = 3;
    IR_ERROR_OBJECT                 = 4;
    IR_ERROR_DIMENSIONS             = 5;
    IR_ERROR_NOT_AVAILABLE          = 6;
    IR_ERROR_OCL_NOT_AVAILABLE      = 7;
    IR_ERROR_OCL_NOT_INITIALIZED    = 8;
    IR_ERROR_OCL_NO_SEARCH_IN_SET   = 9;
    IR_ERROR_OCL_NO_SEARCH_FOR_SET  = 10;
    IR_ERROR_NO_SEARCH_QUEUE_SET    = 11;
    IR_ERROR_OCL_SET_SEARCH_IN      = 12;
    IR_ERROR_OCL_SET_SEARCH_FOR     = 13;
    IR_ERROR_NO_LOAD_QUEUE_SET      = 14;

//* Status types
const
    IR_STATUS_PROGRESS  = 1;

//* Compare type modes
const
    IR_COMPARE_TYPE_EXACT                       = 0;
    IR_COMPARE_TYPE_RELATIVE_ARGB               = 1;
    IR_COMPARE_TYPE_RELATIVE_AHSL               = 2;
    IR_COMPARE_TYPE_RELATIVE_ARGB_ALPHA         = 3;
    IR_COMPARE_TYPE_RELATIVE_AHSL_ALPHA         = 4;

//* Queue modes
const
    IR_SEARCH_MODE_CPU          = 0;
    IR_SEARCH_MODE_OPENCL       = 1;
    IR_SEARCH_MODE_ANY          = 2;

//* Queue threads
const
    IR_THREAD_PRIORITY_IDLE         = 0;
    IR_THREAD_PRIORITY_LOWEST       = 1;
    IR_THREAD_PRIORITY_LOWER        = 2;
    IR_THREAD_PRIORITY_NORMAL       = 3;
    IR_THREAD_PRIORITY_HIGHER       = 4;
    IR_THREAD_PRIORITY_HIGHEST      = 5;
    IR_THREAD_PRIORITY_TIMECRITICAL = 6;

//* Pre-process types
const
    IR_PROCESS_TYPE_NONE        = 0;
    IR_PROCESS_TYPE_RESAMPLE    = 1;

//* Pre-process resample modes
const
    {
    IR_RESAMPLER_BOX         = 0;
    IR_RESAMPLER_LINEAR      = 1;
    IR_RESAMPLER_COSINE      = 2;
    IR_RESAMPLER_SPLINE      = 3;
    IR_RESAMPLER_CUBIC       = 4;
    IR_RESAMPLER_MITCHELL    = 5;
    IR_RESAMPLER_ALBRECHT    = 6;
    IR_RESAMPLER_LANCZOS     = 7;
    IR_RESAMPLER_GAUSSIAN    = 8;
    IR_RESAMPLER_BLACKMAN    = 9;
    IR_RESAMPLER_HANN        = 10;
    IR_RESAMPLER_HAMMING     = 11;
    IR_RESAMPLER_SINSH       = 12;
    IR_RESAMPLER_HERMITE     = 13;
    }
    IR_RESAMPLER_BOX        = 0; // Box, pulse, Fourier window, 1st order (constant) b-spline
    IR_RESAMPLER_BICUBIC    = 1; // Mitchell & Netravali's two-param cubic filter
    IR_RESAMPLER_BILINEAR   = 2; // Bilinear filter
    IR_RESAMPLER_BSPLINE    = 3; // 4th order (cubic) b-spline
    IR_RESAMPLER_CATMULLROM = 4; // Catmull-Rom spline, Overhauser spline
    IR_RESAMPLER_LANCZOS3   = 5; // Lanczos3 filter

type
    TIRStatusCallback = procedure (Progress: Double; StatusType: Integer; User: Pointer); {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};

type
    TIRDimensions = record
        Width: Integer;
        Height: Integer;
    end;

type
    PIRObject = ^TIRObject;
    TIRObject = record
        Status: Integer;
        FileName: PChar;
        ImageObject: Pointer;
        ID: TGUID;
        OriginalDimensions: TIRDimensions;
        ProcessedDimensions: TIRDimensions;
        User: Pointer;
    end;

type
    TIRCreateObjectParameters = record
        ProcessType: Integer;
        Dimensions: TIRDimensions;
        Resampler: Integer;
    end;

type
    TIRProcessParameters = record
        CompareType: Integer;
        ARGBATolerance: Byte;
        ARGBRTolerance: Byte;
        ARGBGTolerance: Byte;
        ARGBBTolerance: Byte;
        AHSLATolerance: Double;
        AHSLHTolerance: Double;
        AHSLSTolerance: Double;
        AHSLLTolerance: Double;
        DifferenceTolerance: Integer;
        StretchCompare: Boolean;            //* Stretch compare is experimental and very slow!
        MinimalStretchSize: TIRDimensions;
        MaximalStretchSize: TIRDimensions;
        StretchResampler: Integer;
        MultipleMatches: Boolean;
        MultiThreadedProcessing: Bool;
        MultiThreadCount: Integer;          //* 0 means all available CPU cores
        StatusCallback: TIRStatusCallback;
        RotateSearch: Bool;
        RotateSearchStartDegrees: Single;
        RotateSearchEndDegrees: Single;
        RotateSearchStepDegrees: Single;
        SearchSorroundingPixels: Bool;
    end;

type
    PIRResultMatches = ^TIRResultMatches;
    TIRResultMatches = record
        Position: TPoint;
        Dimensions: TIRDimensions;
        Angle: Single;
        Difference: Integer;
        MatchPercentage: Single;
    end;

type
    TIRResult = record
        Success: Bool;
        MatchCount: Integer;
        Matches: PIRResultMatches;
    end;

type
    PIROCLDevice = ^TIROCLDevice;
    TIROCLDevice = record
        Instance: Pointer;
        PlatformIndex: Integer;
        DeviceIndex: Integer;
    end;

type
    TIRSearchQueue = record
        Instance: Pointer;
    end;

type
    TIRSearchQueueMatchCallback = procedure (Status: Integer; WorkID: Pointer; CompareResult: TIRResult; User: Pointer); {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    TIRLoadQueueCallback = procedure (Status: Integer; IRObject: TIRObject; User: Pointer); {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    
type
    TIRSearchQueueParameters = record
        OCLDevices: PIROCLDevice;
        OCLDeviceCount: Cardinal;
        OCLThreadPriority: Integer;
        CPUThreads: Cardinal;
        CPUThreadsPriority: Integer;
        ProcessingMode: Integer;
        SearchQueueMatchCallback: TIRSearchQueueMatchCallback;
        SearchQueueMatchMessageHandle: HWND;
        SearchQueueMatchMessageID: Integer;
        User: Pointer;
    end;

type
    TIRSearchQueueWork = record
        IRObjectSearchIn: TIRObject;
        IRObjectSearchFor: TIRObject;
        Parameters: TIRProcessParameters;
        SearchMode: Integer;
        AutoFreeSearchInIRObject: Bool;
        AutoFreeSearchForIRObject: Bool;
        WorkID: Pointer;
    end;

type
    PIRSearchQueueResult = ^TIRSearchQueueResult;
    TIRSearchQueueResult = record
        Status: Integer;
        WorkID: Pointer;
        CompareResult: TIRResult;
        User: Pointer;
    end;

type
    TIRLoadQueue = record
        Instance: Pointer;
    end;

type
    TIRLoadQueueParameters = record
        CPUThreads: Cardinal;
        CPUThreadsPriority: Integer;
        LoadQueueCallback: TIRLoadQueueCallback;
        LoadQueueMessageHandle: HWND;
        LoadQueueMessageID: Integer;
        User: Pointer;
    end;

type
    t_ImageRecognition_CreateObject                 = function (FileName: PChar; var IRObject: TIRObject; Parameters: TIRCreateObjectParameters): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_FreeObject                   = function (var IRObject: TIRObject): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_Compare                      = function (IRObjectSearchIn: TIRObject; IRObjectSearchFor: TIRObject; Parameters: TIRProcessParameters; var CompareResult: TIRResult; User: Pointer): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_FreeResult                   = function (var CompareResult: TIRResult): Bool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_CreateObjectFromBitmapHandle = function (BitmapHandle: HBitmap; var IRObject: TIRObject; Parameters: TIRCreateObjectParameters): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_CreateObjectFromMemory       = function (Address: Pointer; DataSize: UInt64; var IRObject: TIRObject; Parameters: TIRCreateObjectParameters): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLGetPlatform            = function (PlaformIndex: Integer): PChar; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLGetPlatformDevice      = function (PlaformIndex: Integer; DeviceIndex: Integer): PChar; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLInit                   = function (PlaformIndex: Integer; DeviceIndex: Integer; CompareType: Integer; RotateSearch: Bool; ComputeCoreCount: Integer): TIROCLDevice; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLFree                   = function (var OCLDevice: TIROCLDevice): Bool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLSetSearchIn            = function (OCLDevice: TIROCLDevice; IRObjectSearchIn: TIRObject): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLSetSearchFor           = function (OCLDevice: TIROCLDevice; IRObjectSearchFor: TIRObject): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_OpenCLPerformSearch          = function (OCLDevice: TIROCLDevice; Parameters: TIRProcessParameters; var CompareResult: TIRResult; User: Pointer): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_CreateSearchQueue            = function (Parameters: TIRSearchQueueParameters): TIRSearchQueue; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_FreeSearchQueue              = function (var IRSearchQueue: TIRSearchQueue): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_AddSearchWork                = function (IRSearchQueue: TIRSearchQueue; Work: TIRSearchQueueWork): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_FreeSearchQueueResult        = function (var PSearchQueueResult: PIRSearchQueueResult): Bool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_AbortSearchQueue             = function (IRSearchQueue: TIRSearchQueue): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_CreateLoadQueue              = function (Parameters: TIRLoadQueueParameters): TIRLoadQueue; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_FreeLoadQueue                = function (var IRLoadQueue: TIRLoadQueue): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_AddLoadWork                  = function (IRLoadQueue: TIRLoadQueue; FileName: String; Parameters: TIRCreateObjectParameters; User: Pointer): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_AddLoadWorkBitmapHandle      = function (IRLoadQueue: TIRLoadQueue; BitmapHandle: HBitmap; Parameters: TIRCreateObjectParameters; User: Pointer): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_FreeLoadQueueResult          = function (var IRObject: PIRObject): Bool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
    t_ImageRecognition_AbortLoadQueue               = function (IRLoadQueue: TIRLoadQueue): Integer; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};

var
    ImageRecognition_CreateObject: t_ImageRecognition_CreateObject;
    ImageRecognition_FreeObject: t_ImageRecognition_FreeObject;
    ImageRecognition_Compare: t_ImageRecognition_Compare;
    ImageRecognition_FreeResult: t_ImageRecognition_FreeResult;
    ImageRecognition_CreateObjectFromBitmapHandle: t_ImageRecognition_CreateObjectFromBitmapHandle;
    ImageRecognition_CreateObjectFromMemory: t_ImageRecognition_CreateObjectFromMemory;
    ImageRecognition_OpenCLGetPlatform: t_ImageRecognition_OpenCLGetPlatform;
    ImageRecognition_OpenCLGetPlatformDevice: t_ImageRecognition_OpenCLGetPlatformDevice;
    ImageRecognition_OpenCLInit: t_ImageRecognition_OpenCLInit;
    ImageRecognition_OpenCLFree: t_ImageRecognition_OpenCLFree;
    ImageRecognition_OpenCLSetSearchIn: t_ImageRecognition_OpenCLSetSearchIn;
    ImageRecognition_OpenCLSetSearchFor: t_ImageRecognition_OpenCLSetSearchFor;
    ImageRecognition_OpenCLPerformSearch: t_ImageRecognition_OpenCLPerformSearch;
    ImageRecognition_CreateSearchQueue: t_ImageRecognition_CreateSearchQueue;
    ImageRecognition_FreeSearchQueue: t_ImageRecognition_FreeSearchQueue;
    ImageRecognition_AddSearchWork: t_ImageRecognition_AddSearchWork;
    ImageRecognition_FreeSearchQueueResult: t_ImageRecognition_FreeSearchQueueResult;
    ImageRecognition_AbortSearchQueue: t_ImageRecognition_AbortSearchQueue;
    ImageRecognition_CreateLoadQueue: t_ImageRecognition_CreateLoadQueue;
    ImageRecognition_FreeLoadQueue: t_ImageRecognition_FreeLoadQueue;
    ImageRecognition_AddLoadWork: t_ImageRecognition_AddLoadWork;
    ImageRecognition_AddLoadWorkBitmapHandle: t_ImageRecognition_AddLoadWorkBitmapHandle;
    ImageRecognition_FreeLoadQueueResult: t_ImageRecognition_FreeLoadQueueResult;
    ImageRecognition_AbortLoadQueue: t_ImageRecognition_AbortLoadQueue;

var
    ImageRecognitionLibraryHandle: THandle = 0;
    ImageRecognitionLibraryLoaded: Boolean = False;

    function InitImageRecognitionLibrary: Boolean;
    function FreeImageRecognitionLibrary: Boolean;

implementation

Uses
    SysUtils;

function InitImageRecognitionLibrary: Boolean;
begin
    ImageRecognitionLibraryHandle := LoadLibrary(PChar(ImageRecognitionLibraryName));
    Result := ImageRecognitionLibraryHandle <> 0;
    if Result then begin
        ImageRecognition_CreateObject                   := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_CreateObject));
        ImageRecognition_FreeObject                     := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_FreeObject));
        ImageRecognition_Compare                        := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_Compare));
        ImageRecognition_FreeResult                     := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_FreeResult));
        ImageRecognition_CreateObjectFromBitmapHandle   := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_CreateObjectFromBitmapHandle));
        ImageRecognition_CreateObjectFromMemory         := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_CreateObjectFromMemory));
        ImageRecognition_OpenCLGetPlatform              := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLGetPlatform));
        ImageRecognition_OpenCLGetPlatformDevice        := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLGetPlatformDevice));
        ImageRecognition_OpenCLInit                     := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLInit));
        ImageRecognition_OpenCLFree                     := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLFree));
        ImageRecognition_OpenCLSetSearchIn              := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLSetSearchIn));
        ImageRecognition_OpenCLSetSearchFor             := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLSetSearchFor));
        ImageRecognition_OpenCLPerformSearch            := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_OpenCLPerformSearch));
        ImageRecognition_CreateSearchQueue              := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_CreateSearchQueue));
        ImageRecognition_FreeSearchQueue                := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_FreeSearchQueue));
        ImageRecognition_AddSearchWork                  := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_AddSearchWork));
        ImageRecognition_FreeSearchQueueResult          := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_FreeSearchQueueResult));
        ImageRecognition_AbortSearchQueue               := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_AbortSearchQueue));
        ImageRecognition_CreateLoadQueue                := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_CreateLoadQueue));
        ImageRecognition_FreeLoadQueue                  := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_FreeLoadQueue));
        ImageRecognition_AddLoadWork                    := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_AddLoadWork));
        ImageRecognition_AddLoadWorkBitmapHandle        := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_AddLoadWorkBitmapHandle));
        ImageRecognition_FreeLoadQueueResult            := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_FreeLoadQueueResult));
        ImageRecognition_AbortLoadQueue                 := GetProcAddress(ImageRecognitionLibraryHandle, PWideChar(NAME_ImageRecognition_AbortLoadQueue));

    end;
    if (@ImageRecognition_CreateObject = nil)
    OR (@ImageRecognition_FreeObject = nil)
    OR (@ImageRecognition_Compare = nil)
    OR (@ImageRecognition_FreeResult = nil)
    OR (@ImageRecognition_CreateObjectFromBitmapHandle = nil)
    OR (@ImageRecognition_CreateObjectFromMemory = nil)
    OR (@ImageRecognition_OpenCLGetPlatform = nil)
    OR (@ImageRecognition_OpenCLGetPlatformDevice = nil)
    OR (@ImageRecognition_OpenCLInit = nil)
    OR (@ImageRecognition_OpenCLFree = nil)
    OR (@ImageRecognition_OpenCLSetSearchIn = nil)
    OR (@ImageRecognition_OpenCLSetSearchFor = nil)
    OR (@ImageRecognition_OpenCLPerformSearch = nil)
    OR (@ImageRecognition_CreateSearchQueue = nil)
    OR (@ImageRecognition_FreeSearchQueue = nil)
    OR (@ImageRecognition_AddSearchWork = nil)
    OR (@ImageRecognition_FreeSearchQueueResult = nil)
    OR (@ImageRecognition_AbortSearchQueue = nil)
    OR (@ImageRecognition_CreateLoadQueue = nil)
    OR (@ImageRecognition_FreeLoadQueue = nil)
    OR (@ImageRecognition_AddLoadWork = nil)
    OR (@ImageRecognition_AddLoadWorkBitmapHandle = nil)
    OR (@ImageRecognition_FreeLoadQueueResult = nil)
    OR (@ImageRecognition_AbortLoadQueue = nil)
    then begin
    	FreeLibrary(ImageRecognitionLibraryHandle);
    	Result := False;
    end;
    if Result
        then ImageRecognitionLibraryLoaded := True;
end;

function FreeImageRecognitionLibrary: Boolean;
begin
    Result := False;
    if ImageRecognitionLibraryHandle <> 0 then begin
        Result := FreeLibrary(ImageRecognitionLibraryHandle);
        if Result then begin
            ImageRecognitionLibraryHandle := 0;
            ImageRecognitionLibraryLoaded := False;
        end;
    end;
end;

Initialization

    InitImageRecognitionLibrary;

Finalization

    FreeImageRecognitionLibrary;

end.
